<?php

namespace Yj\Generator\Core\Model;


use Yj\Generator\Core\Model\Traits\DocBlockTrait;

/**
 * @Notes: []
 * @User: zwc
 * @Date: 2022/2/28 19:43
 */
class ClassModel extends RenderableModel
{
    use DocBlockTrait;

    /**
     * @var ClassNameModel
     */
    protected $name;

    /**
     * @return ClassNameModel
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @var string
     */
    protected $extends;

    /**
     * @var NamespaceModel
     */
    protected $namespace;

    /**
     * @var UseTraitModel[]
     */
    protected $traits = [];

    /**
     * @return NamespaceModel
     */
    public function getNamespace(): NamespaceModel
    {
        return $this->namespace;
    }

    /**
     * @param NamespaceModel $namespace
     */
    public function setNamespace(NamespaceModel $namespace): void
    {
        $this->namespace = $namespace;
    }


    /**
     * @param string $name
     *
     * @return $this
     */
    public function setName(ClassNameModel $name)
    {
        $this->name = $name;

        return $this;
    }


    /**
     * @param string $extends
     *
     * @return $this
     */
    public function setExtends($extends)
    {
        $this->extends = $extends;

        return $this;
    }

    /**
     * @return UseTraitModel[]
     */
    public function getTraits()
    {
        return $this->traits;
    }

    /**
     * @param UseTraitModel
     *
     * @return $this
     */
    public function addTrait(UseTraitModel $trait)
    {

        $this->traits[] = $trait;
        return $this;
    }


    public function toLines()
    {
        $lines = [];
        $lines[] = $this->ln('<?php');

        if ($this->namespace !== null) {
            $lines[] = $this->ln($this->namespace->render());
        }

        $this->prepareDocBlock();


        if (count($this->uses) > 0) {
            $lines[] = $this->renderArrayLn($this->uses);
        }

        if ($this->docBlock !== null) {
            $lines[] = $this->docBlock->render();
        }

        $lines[] = $this->name?->render();


        if (count($this->traits) > 0) {
            $lines[] = $this->renderArrayLn($this->traits, 4);
        }

        $this->processProperties($lines);

        $lines[] = $this->ln('}');
        return $lines;
    }

    protected function processProperties(&$lines)
    {
        $properties = array_filter($this->properties, function ($property) {
            return !$property instanceof VirtualPropertyModel;
        });
        if (count($properties) > 0) {
            $lines[] = $this->renderArrayLn($properties, 4, str_repeat(PHP_EOL, 2));
        }
    }


    private function prepareDocBlock()
    {
        $content = [];
        foreach ($this->properties as $property) {
            if ($property instanceof VirtualPropertyModel) {
                $content[] = $property->toLines();
            }
        }

        if ($content) {
            if ($this->docBlock === null) {
                $this->docBlock = new DocBlockModel();
            }
            $this->docBlock->addContent($content);
        }
    }


    /**
     * @var UseClassModel[]
     */
    protected $uses = [];

    public function addUses(UseClassModel $use)
    {

        $this->uses[] = $use;

        return $this;
    }
}